//
//  Scene.hpp
//  RayTracer
//
//  Created by 俞云康 on 2/15/16.
//  Copyright © 2016 yushroom. All rights reserved.
//

#ifndef Scene_hpp
#define Scene_hpp

#include "Math.hpp"
#include "Shape.hpp"
#include "HitInfo.hpp"
#include "Light.hpp"
#include "KDTree.hpp"
#include <vector>

#define USE_KDTREE 1

class Params;

class Scene {
public:
    std::vector<std::shared_ptr<Light>> lights;
    std::vector<std::shared_ptr<AreaLight>> area_lights;
    std::vector<std::shared_ptr<GeometricPrimitive>> geometricPrimitives;
    std::vector<std::shared_ptr<TriangleMesh>> meshes;
    std::shared_ptr<KDTree> mKDtree;
    
public:
    static shared_ptr<Scene> create(const Params& params);
    
    void add(const std::shared_ptr<GeometricPrimitive> geometricPrimitive);
    void add(const std::shared_ptr<Light>       light);
    void add(const std::shared_ptr<AreaLight>   light);
    
    inline bool intersect(const Ray& r, HitInfo* hit) const {
#if USE_KDTREE
        return mKDtree->intersect(r, hit);
#else
        bool h = false;
        for (auto& gp : geometricPrimitives) {
            if (gp->intersect(r, hit))
                h = true;
        }
        return h;
#endif
    }
    
    inline bool intersect(const Ray& r) const {
#if USE_KDTREE
        return mKDtree->intersect(r);
#else
        for (auto& gp : geometricPrimitives) {
            if (gp->intersect(r))
                return true;
        }
        return false;
#endif
    }
    
    AABB worldBounds() const {
        return mKDtree->worldBounds();
    }
};


#endif /* Scene_hpp */
